#ifndef     __MUTEX_H
#define     __MUTEX_H

#include "./rtos.h"
#include "../utils/assert.h"
#include "../utils/no_copyable.h"

namespace rtos {

class Mutex : private utils::no_copyable_t {
public:
    class Auto : private utils::no_copyable_t {
    public:
        inline Auto(Mutex &m) : m_mutex(m) {
            m_mutex.lock();
        }
        inline ~Auto() {
            m_mutex.unlock();
        }

    private:
        Mutex &m_mutex;        
    };

    Mutex(const char *name = "other") {
        osMutexAttr_t attr;
        attr.name = name;
        attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxMutexCbSize;
        m_id = osMutexNew(&attr);
        utils::assert(m_id != NULL);
    }

    inline osStatus_t lock() {
        return osMutexAcquire(m_id, osWaitForever);
    }

    inline osStatus_t unlock() {
        return osMutexRelease(m_id);
    }

private:
    osMutexId_t m_id;
    uint64_t m_cb_mem[(osRtxMutexCbSize + 7) / 8]; 
};

}


#endif
